package com.warm.common.word;

import com.alibaba.fastjson.JSONObject;
import com.warm.common.util.QRCodeUtil;
import com.warm.common.word.Word;
import freemarker.template.Configuration;
import freemarker.template.Template;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;
import org.springframework.util.FileCopyUtils;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Base64;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

@Slf4j
public class ExcelUtil {
    private static String templatePath = "D:\\personal\\practice\\common\\static\\excel";
    private static String templateFilePath = "D:\\personal\\practice\\common\\static\\excel\\excel.xlsx";
    private static String sheet1Path = "D:\\personal\\practice\\common\\static\\excel\\sheet1.xml";

    // 初始化配置
    private static Configuration configuration;
    
    private static String TEMP_File_PATH = "./temp/";

    // 分隔符
    private static String separator = "/";

    public static void init(String templatePath){
        File baseDir = new File(templatePath);
        if(!baseDir.exists()){
            baseDir.mkdirs();
        }
        //创建配置实例
        Configuration ins = new Configuration(Configuration.VERSION_2_3_0);
        //设置编码
        ins.setDefaultEncoding("utf-8");
        try {
            ins.setDirectoryForTemplateLoading(new File(templatePath));
        } catch (IOException e) {
            e.printStackTrace();
        }

        configuration = ins;
    }

    public static void exportExcel(JSONObject obj){
        new File(TEMP_File_PATH).mkdirs();
        exportExcel(obj, TEMP_File_PATH + System.currentTimeMillis() + ".xlsx");
    }

    public static void exportExcel(JSONObject obj, String tempPath) {
        init(templatePath); // 初始化配置

        ZipOutputStream zipout = null;
        OutputStream os = null;
        try {
            os = new FileOutputStream(tempPath);
            zipout = new ZipOutputStream(os);
            File templateSourceFile = new File(templateFilePath);

            ZipFile zipFile = new ZipFile(templateSourceFile);
            // 把模板中其他的文件 复制到zipout流中, 填充图片、文本内容
            coverFile(zipFile, zipout, obj);
        } catch (Exception e) {
            log.error("word导出失败:",e);
        }finally {
            closeZipStream(zipout);
            closeOutStream(os);
        }
    }

    private static void coverFile(ZipFile zipFile, ZipOutputStream zipout, JSONObject obj) throws IOException {
        Enumeration<? extends ZipEntry> zipEntrys = zipFile.entries();
        //图片配置文件模板
        ByteArrayInputStream sheet1Input = getFreemarkerContentInputStream(obj, "sheet1.xml");

        //ByteArrayInputStream xlRelsInput = getFreemarkerContentInputStream(obj, "workbook.xml.rels");

        int len = -1;
        byte[] buffer = new byte[1024];
        //开始覆盖文档
        while (zipEntrys.hasMoreElements()) {
            ZipEntry next = zipEntrys.nextElement();
            zipout.putNextEntry(new ZipEntry(next.getName()));
            /*if("xl/sharedStrings.xml".equals(next.getName())){
                continue;
            }*/
            if("xl/worksheets/sheet1.xml".equals(next.getName())){ // 图片
                if (sheet1Input != null) {
                    while ((len = sheet1Input.read(buffer)) != -1) {
                        zipout.write(buffer, 0, len);
                    }
                    sheet1Input.close();
                }
            } /*else if("xl/_rels/workbook.xml.rels".equals(next.getName())){
                if (xlRelsInput != null) {
                    while ((len = xlRelsInput.read(buffer)) != -1) {
                        zipout.write(buffer, 0, len);
                    }
                    xlRelsInput.close();
                }
            }*/ else { // 其他文件
                InputStream is = zipFile.getInputStream(next);
                while ((len = is.read(buffer)) != -1) {
                    zipout.write(buffer, 0, len);
                }
                is.close();
            }
        }
    }


    /**
     * 渲染模板
     * @param obj   参数
     * @param templateName  模板名称
     * @return
     */
    public static ByteArrayInputStream getFreemarkerContentInputStream(JSONObject obj, String templateName) {
        ByteArrayInputStream in = null;
        try {
            Template template = configuration.getTemplate(templateName);
            StringWriter swriter = new StringWriter();

            template.process(obj, swriter);
            in = new ByteArrayInputStream(swriter.toString().getBytes("utf-8"));//这里一定要设置utf-8编码 否则导出的word中中文会是乱码
        } catch (Exception e) {
            log.error("模板生成错误！",e);
        }
        return in;
    }

    public static InputStream file2InputStream(String filepath){
        InputStream in = null;
        try {
            File file = new File(filepath);
            if(file.exists()){
                in = new FileInputStream(file);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return in;
    }

    public static InputStream url2InputStream(String fileUrl){
        InputStream in = null;
        try {
            URL url = new URL(fileUrl);
            in = url.openStream();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return in;
    }

    public static String url2Base64Str(String fileUrl){
        HttpURLConnection conn = null;
        InputStream inputStream = null;
        try {
            conn = (HttpURLConnection) new URL(fileUrl).openConnection();
            conn.setRequestMethod("GET");
            conn.setConnectTimeout(5000);
            inputStream = conn.getInputStream();
            return Base64.getEncoder().encodeToString(FileCopyUtils.copyToByteArray(inputStream));
        } catch (Exception e) {
            System.out.println(e.getMessage());
        } finally {
            closeInStream(inputStream);
            if(conn != null) {
                conn.disconnect();
            }
        }
        return null;
    }

    private static void closeZipStream(ZipOutputStream zipout){
        if(zipout == null) return;
        try {
            zipout.close();
        } catch (IOException e) {
            log.error("io异常");
        }
    }

    private static void closeOutStream(OutputStream os){
        if(os == null) return;
        try {
            os.close();
        } catch (IOException e) {
            log.error("io异常");
        }
    }

    private static void closeInStream(InputStream in){
        if(in == null) return;
        try {
            in.close();
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }
}
